package com.moody.calculator;

import com.moody.util.NormalDistributionUtil;

/*
 * Copyright © Moody analytics
 *
 * @Author: liupeng
 * @Time: 2011-11-21 下午01:35:56
 * @Modified by: 经济资本测算所用公式
 * @Description: 
 */
public class RiskAppCalculator {
	public static final int SOVEREIGNTY = 1;
	public static final int COMPANY_COMMON = 2;
	public static final int FINANCE = 3;
	public static final int COMPANY_SMALL = 4;
	public static final int RETAIL_MORTGAGE = 5;
	public static final int RETAIL_RECYCLE = 6;
	public static final int RETAIL_OTHERS = 7;
	
	public static double calculateK(double lgd, double pd,int expFlag, double...params){
		double R = 0;
		double M = 2.5;//??????????????????????????????????
		double b = calculateB(pd);
		if(params.length == 1) R = calculateR(pd, expFlag, params[0]);
		else R = calculateR(pd,expFlag);
		
		double k = lgd*NormalDistributionUtil.NormSDist(Math.sqrt(1/(1-R))*NormalDistributionUtil.NormSInv(pd) + Math.sqrt(R/(1-R))*NormalDistributionUtil.NormSInv(0.999)) - pd*lgd;
		if(expFlag == SOVEREIGNTY || expFlag == COMPANY_COMMON || expFlag == FINANCE || expFlag == COMPANY_SMALL){
			k = k * ((1 + (M-2.5)*b)/(1 - 1.5*b));
		}
//		double G_pd = NormalDistributionUtil.NormSInv(pd);
//		double G_0999 = NormalDistributionUtil.NormSInv(0.999);
//		double x_N = Math.sqrt(1/(1-R))*NormalDistributionUtil.NormSInv(pd) + Math.sqrt(R/(1-R))*NormalDistributionUtil.NormSInv(0.999);
//		double N = NormalDistributionUtil.NormSDist(-1.236444343);
		return k;
	}
	
	public static double calculateR(double pd, int expFlag, double...params){
		double r = 0.12 * ((1-1/Math.exp(50*pd))/(1-1/Math.exp(50))) + 0.24 * (1-((1-1/Math.exp(50*pd))/(1-1/Math.exp(50))));
		if(expFlag == SOVEREIGNTY || expFlag == COMPANY_COMMON){
			return r;
		}
		else if (expFlag == FINANCE){
			return 1.25 * r;
		}
		else if(expFlag == COMPANY_SMALL){
			double S = 3;
			if(params.length == 1) {
				S = params[0] / 10000000;
				if(S < 3) S = 3;
			}
			return r - 0.04 * (1 - (S - 3) / 27);
		}
		else if(expFlag == RETAIL_MORTGAGE){
			return 0.15;
		}
		else if(expFlag == RETAIL_RECYCLE){
			return 0.04;
		}
		else if(expFlag == RETAIL_OTHERS){
			return 0.03 * ((1-1/Math.exp(35*pd))/(1-1/Math.exp(35))) + 0.16 * (1-((1-1/Math.exp(35*pd))/(1-1/Math.exp(35))));
		}
		else return 0;
	}
	
	public static double calculateB(double pd){
		return Math.pow(0.11852 - 0.05478 * Math.log(pd),2);
	}
	
	public static double G(double x){
		return 1;
	}
	
}
